#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member

using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;

namespace EntityKit.Runtime
{
    /// <summary>
    /// CancellationToken 扩展方法
    /// </summary>
    public static class CancellationTokenExtensions
    {
        /// <summary>
        /// 获取一个与 GameObject 生命周期绑定的 CancellationToken
        /// 当 GameObject 被销毁时，该 Token 会被取消
        /// </summary>
        /// <param name="component">组件</param>
        /// <returns>CancellationToken</returns>
        public static CancellationToken GetGameObjectDestroyToken(this Component component)
        {
            if (component == null)
                throw new System.ArgumentNullException(nameof(component));
            
            return component.gameObject.GetAsyncDestroyTrigger().CancellationToken;
        }
        
        public static CancellationToken GetGameObjectDestroyToken(this GameObject gameObject)
        {
            if (gameObject == null)
                throw new System.ArgumentNullException(nameof(gameObject));
            return gameObject.GetAsyncDestroyTrigger().CancellationToken;
        }
        
        /// <summary>
        /// 将CancellationToken转换为Task
        /// </summary>
        /// <param name="cancellationToken">CancellationToken</param>
        /// <returns>当CancellationToken被取消时完成的Task</returns>
        public static Task AsTask(this CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
                return Task.CompletedTask;

            var tcs = new TaskCompletionSource<bool>();
            cancellationToken.Register(() => tcs.SetResult(true));
            return tcs.Task;
        }
        
        /// <summary>
        /// 创建一个在指定时间后自动取消的CancellationToken
        /// </summary>
        /// <param name="delay">延迟时间（毫秒）</param>
        /// <returns>CancellationToken</returns>
        public static CancellationToken AfterDelay(int delay)
        {
            var cts = new CancellationTokenSource();
            cts.CancelAfter(delay);
            return cts.Token;
        }
        
        /// <summary>
        /// 创建一个在指定时间后自动取消的CancellationToken
        /// </summary>
        /// <param name="delay">延迟时间</param>
        /// <returns>CancellationToken</returns>
        public static CancellationToken AfterDelay(System.TimeSpan delay)
        {
            var cts = new CancellationTokenSource();
            cts.CancelAfter(delay);
            return cts.Token;
        }
        
        /// <summary>
        /// 创建一个组合的CancellationToken，当任意一个Token被取消时，组合Token也会被取消
        /// </summary>
        /// <param name="first">第一个CancellationToken</param>
        /// <param name="second">第二个CancellationToken</param>
        /// <returns>组合的CancellationToken</returns>
        public static CancellationToken CombineWith(this CancellationToken first, CancellationToken second)
        {
            if (first.IsCancellationRequested)
                return first;
            
            if (second.IsCancellationRequested)
                return second;
            
            var cts = CancellationTokenSource.CreateLinkedTokenSource(first, second);
            return cts.Token;
        }
    }
}